<script setup lang="ts">
import type { EquipmentClassification, EquipmentDefinition } from '@/types'

import ItemComponent from './components/item-component.vue'
import TextComponent from './components/text-component.vue'
import RadioComponent from './components/radio-component.vue'
import SelectComponent from './components/select-component.vue'
import DateComponent from './components/date-component.vue'
import FileComponent from './components/file-component.vue'
import { EQUIPMENT_COMPONENT_TYPE, EQUIPMENT_INPUT_DATA_TYPE } from '@/enum'
import { BASE, SPECIFICATION, PICTURE, ATTACHMENT } from './constant'
import { cloneDeep } from 'lodash-es'

defineOptions({
  name: 'EquipmentDefinition',
})

const componentRef = ref()
const typeKey = ref()

const equipmentStore = useEquipmentStore()

const types = computed(() => {
  return equipmentStore.types
})
const data = ref<EquipmentClassification[]>([])

const showTextButton = ref(false)
const showRadioButton = ref(false)
const showSelectButton = ref(false)
const showDateButton = ref(false)
const showAttachmentButton = ref(false)

const loading = ref(false)

const tabId = ref(BASE)

watchEffect(() => {
  switch (unref(tabId)) {
    case SPECIFICATION:
      showTextButton.value = true
      showRadioButton.value = false
      showSelectButton.value = false
      showDateButton.value = false
      showAttachmentButton.value = false
      break
    case PICTURE:
      showTextButton.value = false
      showRadioButton.value = false
      showSelectButton.value = false
      showDateButton.value = false
      // 初始化会有3条图片定义信息
      showAttachmentButton.value = false
      break
    case ATTACHMENT:
      showTextButton.value = false
      showRadioButton.value = false
      showSelectButton.value = false
      showDateButton.value = false
      showAttachmentButton.value = true
      break
    default:
      showTextButton.value = true
      showRadioButton.value = true
      showSelectButton.value = true
      showDateButton.value = true
      showAttachmentButton.value = false
  }
})

function append(type: EQUIPMENT_COMPONENT_TYPE, list: EquipmentDefinition[]) {
  list.push({
    _uuid: uuid(),
    id: null,
    name: '',
    type,
    urlAddr: '',
    dataType: unref(tabId) === SPECIFICATION ? EQUIPMENT_INPUT_DATA_TYPE.POINT : EQUIPMENT_INPUT_DATA_TYPE.TEXT,
    required: 0,
    multipleAttachments: 0,
    fixed: 0,
    value: null,
    parameter: null,
    attachments: null,
  })
}
function remove(_uuid: string, list: EquipmentDefinition[]) {
  const index = list.findIndex(item => item._uuid === _uuid)
  if (index > -1) {
    list.splice(index, 1)
  }
}

function move(_uuid: string, list: EquipmentDefinition[], direction: 'top' | 'bottom') {
  const index = list.findIndex(item => item._uuid === _uuid)
  if (direction === 'top') {
    // 上移
    if (index > 0) {
      const temp = list[index - 1]
      list[index - 1] = list[index]
      list[index] = temp
    }
  }
  else if (direction === 'bottom') {
    // 下移
    if (index < list.length - 1) {
      const temp = list[index + 1]
      list[index + 1] = list[index]
      list[index] = temp
    }
  }
}

function getListByAnchor(anchor: string) {
  return unref(data).find(v => v.key === anchor)?.list ?? []
}

function handleAdd(type: EQUIPMENT_COMPONENT_TYPE) {
  const anchor = unref(tabId)
  const list = getListByAnchor(anchor)
  append(type, list as EquipmentDefinition[])
}

async function handleRemove(id: string) {
  remove(id, getListByAnchor(unref(tabId)))
}

async function handleMove(id: string | number, direction: 'top' | 'bottom') {
  move(id as string, getListByAnchor(unref(tabId)), direction)
}

async function handleSave() {
  const cs = componentRef.value ?? []
  const errors: boolean[] = []
  for (const item of cs) {
    errors.push(item.validate())
  }
  // console.log(errors)
  if (errors.every(v => v === true)) {
    await equipmentDefinitionApi.saveDefinitionInfo(
      unref(typeKey),
      getSaveParams(),
    )
    ElMessage.success('保存成功')
    await getList()
  }
  else {
    ElMessage.error('请完善设备定义数据')
  }
}

function getSaveParams() {
  const d = cloneDeep(unref(data))
  for (const item of d) {
    for (const subItem of item.list) {
      if (typeof subItem.id !== 'number') {
        subItem.id = ''
      }
    }
  }
  return d
}

async function getList() {
  if (!unref(typeKey))
    return
  loading.value = true
  const old = unref(data)
  try {
    data.value = []
    const res = await equipmentStore.getDefinitions({
      typeKey: unref(typeKey),
    })
    data.value = res
  }
  catch (error) {
    data.value = old
  }
  finally {
    loading.value = false
  }
}

function isPoint(scope: EquipmentDefinition) {
  return data.value.find(v => v.list.includes(scope))?.key === SPECIFICATION
}

// 上移按钮 disabled 状态
function disableTopButton(item: EquipmentDefinition, list: EquipmentDefinition[]) {
  // 第一个，或者前一个是“固定”的
  return item === list[0] || list[list.indexOf(item) - 1].fixed === 1
}

// 下移按钮 disabled 状态
function disableBottomButton(item: EquipmentDefinition, list: EquipmentDefinition[]) {
  // 最后一个，或者后一个是“固定”的
  return item === list[list.length - 1] || list[list.indexOf(item) + 1].fixed === 1
}

watch(types, () => {
  typeKey.value = types.value[0].key
})

watch(typeKey, () => {
  getList()
})
</script>

<template>
  <div class="h-full w-full flex items-center p-4">
    <div class="alpha-block h-full w-50 flex-shrink-0">
      <div class="h-full w-full flex flex-col">
        <div class="p-3">
          设备类型
        </div>
        <div class="flex-auto overflow-auto">
          <div
            v-for="item in types" :key="item.key"
            class="fs-14 type-item cursor-pointer px-3 py-2 opacity-80 transition-all hover:opacity-100"
            :class="{ active: typeKey === item.key }"
            @click="typeKey = item.key"
          >
            {{ item.value }}
          </div>
        </div>
      </div>
    </div>
    <div class="alpha-block ml-4 h-full flex-auto">
      <div v-loading="loading" element-loading-custom-class="global-loading" class="h-full w-full flex items-center">
        <div class="h-full flex-shrink-0 overflow-auto px-1 py-3">
          <ElTabs v-model="tabId" tab-position="left" class="h-full">
            <ElTabPane v-for="item in data" :key="item.key" :label="item.name" :name="item.key" />
          </ElTabs>
        </div>
        <div class="h-full flex flex-auto flex-col overflow-auto">
          <div class="flex flex-shrink-0 items-center justify-end p-3">
            <ElButton v-if="showTextButton" type="warning" plain @click="handleAdd(EQUIPMENT_COMPONENT_TYPE.TEXT)">
              新增文本
            </ElButton>
            <ElButton v-if="showRadioButton" type="warning" plain @click="handleAdd(EQUIPMENT_COMPONENT_TYPE.RADIO)">
              新增单选
            </ElButton>
            <ElButton v-if="showSelectButton" type="warning" plain @click="handleAdd(EQUIPMENT_COMPONENT_TYPE.SELECT)">
              新增列表
            </ElButton>
            <ElButton v-if="showDateButton" type="warning" plain @click="handleAdd(EQUIPMENT_COMPONENT_TYPE.DATE)">
              新增日期
            </ElButton>
            <ElButton v-if="showAttachmentButton" type="warning" plain @click="handleAdd(EQUIPMENT_COMPONENT_TYPE.ATTACHMENT)">
              新增附件
            </ElButton>
            <ElButton type="success" @click="handleSave">
              保存
            </ElButton>
          </div>
          <div class="flex-auto overflow-x-hidden overflow-y-auto py-3">
            <template v-for="item in data" :key="item.key">
              <div v-show="tabId === item.key">
                <ItemComponent :item="item" :type-key="typeKey">
                  <template #default="scope">
                    <TextComponent v-if="+scope.definition.type === EQUIPMENT_COMPONENT_TYPE.TEXT" ref="componentRef" v-model="scope.definition" class="move" :disabled="!!scope.definition.fixed" :is-point="isPoint(scope.definition)" :show-top-button="scope.definition.fixed !== 1" :show-bottom-button="scope.definition.fixed !== 1" :disable-top-button="disableTopButton(scope.definition, item.list)" :disable-bottom-button="disableBottomButton(scope.definition, item.list)" @move="(id, direction) => handleMove(id, direction)" @remove="handleRemove(scope.definition._uuid)" />
                    <RadioComponent v-else-if="+scope.definition.type === EQUIPMENT_COMPONENT_TYPE.RADIO" ref="componentRef" v-model="scope.definition" class="move" :disabled="!!scope.definition.fixed" :show-top-button="scope.definition.fixed !== 1" :show-bottom-button="scope.definition.fixed !== 1" :disable-top-button="disableTopButton(scope.definition, item.list)" :disable-bottom-button="disableBottomButton(scope.definition, item.list)" @move="(id, direction) => handleMove(id, direction)" @remove="handleRemove(scope.definition._uuid)" />
                    <SelectComponent v-else-if="+scope.definition.type === EQUIPMENT_COMPONENT_TYPE.SELECT" ref="componentRef" v-model="scope.definition" class="move" :disabled="!!scope.definition.fixed" :show-top-button="scope.definition.fixed !== 1" :show-bottom-button="scope.definition.fixed !== 1" :disable-top-button="disableTopButton(scope.definition, item.list)" :disable-bottom-button="disableBottomButton(scope.definition, item.list)" @move="(id, direction) => handleMove(id, direction)" @remove="handleRemove(scope.definition._uuid)" />
                    <DateComponent v-else-if="+scope.definition.type === EQUIPMENT_COMPONENT_TYPE.DATE" ref="componentRef" v-model="scope.definition" class="move" :disabled="!!scope.definition.fixed" :show-top-button="scope.definition.fixed !== 1" :show-bottom-button="scope.definition.fixed !== 1" :disable-top-button="disableTopButton(scope.definition, item.list)" :disable-bottom-button="disableBottomButton(scope.definition, item.list)" @move="(id, direction) => handleMove(id, direction)" @remove="handleRemove(scope.definition._uuid)" />
                    <FileComponent v-else-if="+scope.definition.type === EQUIPMENT_COMPONENT_TYPE.ATTACHMENT" ref="componentRef" v-model="scope.definition" class="move" :show-top-button="scope.definition.fixed !== 1" :show-bottom-button="scope.definition.fixed !== 1" :disable-top-button="disableTopButton(scope.definition, item.list)" :disable-bottom-button="disableBottomButton(scope.definition, item.list)" @move="(id, direction) => handleMove(id, direction)" @remove="handleRemove(scope.definition._uuid)" />
                  </template>
                </ItemComponent>
              </div>
            </template>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.type-item.active {
  opacity: 100;
  color: var(--el-color-primary);
}
</style>
